/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

#include "StdAfx.h"
#include ".\workcfg.h"

#include <algorithm>

//---------------------------------------------------------------------------

WorkCfg::WorkCfg(void) : MFileConfig()
{
	Initialize();
}

WorkCfg::~WorkCfg(void)
{
	CleanUp();
}

//---------------------------------------------------------------------------

void WorkCfg::CleanUp(void)
{
	WorkCfgElement *elem;

	for(itor=theVector.begin(); itor!=theVector.end(); itor++){
		elem = *itor;
		if(elem!=NULL){
			*itor = NULL;
			delete elem;
		}
	}
	theVector.clear();
}

//---------------------------------------------------------------------------

WorkCfgElement* WorkCfg::CreateWorkCfgElement(void)
{
	WorkCfgElement* elem;

	try{
		elem = new WorkCfgElement;
	}
	catch(...){
		elem = NULL;
	}

	return elem;
}

WorkCfgElement* WorkCfg::CreateWorkCfgElement(WorkCfgElement* wceIn)
{
	WorkCfgElement* elem;

	elem = CreateWorkCfgElement();
	if(elem==NULL) return elem;

	elem->LoadFromPointer(wceIn);

	return elem;
}

//---------------------------------------------------------------------------

void WorkCfg::Initialize(void)
{
	xFileName.Empty();

	xDescription.Empty();
	xComment.Empty();

	xAddresses.Empty();

	xShowArpDiscoveredHosts = true;
	xScanAll                = false;
	xScanOrder              = __soAsEntered;

	xMaxSimScan             = 100;
	xMaxSimScanDns          = 4;
	xMaxSimScanIcmp         = 2;
	xMaxWaitTime            = 1000;
	xMinDelay               = 0;

	xMimicOS                = __mosRandom;

	xArpCacheOp             = __acoIgnore;

	CleanUp();

	idLen = 22;

	xHuntMode    = false;
	xPassiveMode = false;
}

//---------------------------------------------------------------------------

void WorkCfg::ClearJobList(void)
{
	CleanUp();
}

bool WorkCfg::AddJob(WorkCfgElement* wceIn)
{
	WorkCfgElement* wce;
	int cnt;

	if(wceIn==NULL) return true; // nothing to add

	wce = CreateWorkCfgElement(wceIn);
	if(wce==NULL) return false;

	cnt = (int)theVector.size();
	theVector.push_back(wce);
	cnt = (int)theVector.size() - cnt;
	if(cnt!=1){
		delete wce;
		return false;
	}

	return true;
}

bool WorkCfg::DeleteJob(WorkCfgElement* wceIn)
{
	WorkCfgElement *wce;

	for(itor=theVector.begin(); itor!=theVector.end(); itor++){
		wce = *itor;
		if(wce==wceIn){
			theVector.erase(itor);
			if(wce!=NULL)
				delete wce;
			return true;
		}
	}

	return false;
}

bool WorkCfg::AddAllJobsFromList(WorkCfg* wcIn)
{
	WorkCfgElement *wce;
	int i, cnt;
	bool res;

	ClearJobList();

	if(wcIn==NULL) return true;

	res = true;
	cnt = wcIn->GetJobCount();
	for(i=0; i<cnt && res; i++){
		wce = wcIn->GetJobElement(i);
		if(wce!=NULL)
			res = AddJob(wce);
	}

	if(!res)
		ClearJobList();

	return res;
}

//---------------------------------------------------------------------------

WorkCfg& WorkCfg::operator = (WorkCfg& wcIn)
{
	xFileName               = wcIn.xFileName;
	xDescription            = wcIn.xDescription;
	xComment                = wcIn.xComment;
	xAddresses              = wcIn.xAddresses;
	xShowArpDiscoveredHosts = wcIn.xShowArpDiscoveredHosts;
	xScanAll                = wcIn.xScanAll;
	xScanOrder              = wcIn.xScanOrder;
	xMaxSimScan             = wcIn.xMaxSimScan;
	xMaxSimScanDns          = wcIn.xMaxSimScanDns;
	xMaxSimScanIcmp         = wcIn.xMaxSimScanIcmp;
	xMaxWaitTime            = wcIn.xMaxWaitTime;
	xMinDelay               = wcIn.xMinDelay;
	xMimicOS                = wcIn.xMimicOS;
	xArpCacheOp             = wcIn.xArpCacheOp;

	AddAllJobsFromList(&wcIn);

	Check();

	xHuntMode               = wcIn.xHuntMode;
	xPassiveMode            = wcIn.xPassiveMode;

	return (*this);
}

//---------------------------------------------------------------------------

bool WorkCfg::LoadFromPointer(WorkCfg* wcIn)
{
	bool res;

	if(wcIn==NULL){
		Initialize();
		return true;
	}

	xFileName               = wcIn->xFileName;
	xDescription            = wcIn->xDescription;
	xComment                = wcIn->xComment;
	xAddresses              = wcIn->xAddresses;
	xShowArpDiscoveredHosts = wcIn->xShowArpDiscoveredHosts;
	xScanAll                = wcIn->xScanAll;
	xScanOrder              = wcIn->xScanOrder;
	xMaxSimScan             = wcIn->xMaxSimScan;
	xMaxSimScanDns          = wcIn->xMaxSimScanDns;
	xMaxSimScanIcmp         = wcIn->xMaxSimScanIcmp;
	xMaxWaitTime            = wcIn->xMaxWaitTime;
	xMinDelay               = wcIn->xMinDelay;
	xMimicOS                = wcIn->xMimicOS;
	xArpCacheOp             = wcIn->xArpCacheOp;
	
	res = AddAllJobsFromList(wcIn);

	Check();

	xHuntMode               = wcIn->xHuntMode;
	xPassiveMode            = wcIn->xPassiveMode;

	return res;
}

//---------------------------------------------------------------------------

int WorkCfg::GetJobsCount(WorkPhaseType phaseIn)
{
	WorkCfgElement *wce;
	int res;

	res = 0;
	for(itor=theVector.begin(); itor!=theVector.end(); itor++){
		wce = *itor;
		if(wce!=NULL){
			if(wce->phaseType==phaseIn)
				res ++;
		}
	}

	return res;
}

//---------------------------------------------------------------------------

void WorkCfg::InternalInit(void)
{
	Initialize();
}

//---------------------------------------------------------------------------

bool WorkCfg::InternalProcessLine(char* buf)
{
	WorkCfgElement wce;
	CString str, strId;
	ScanOrder scanOrd;
	int pos;

	if(buf==NULL){
		// nothing to process
		return true;
	}

	str = buf;
	pos = str.Find('=');
	if(pos==-1){
		// invalid line
		return false;
	}

	strId = str.Left(pos);
	strId = strId.Trim();

	str = str.Mid(pos+1);
	str = str.Trim();

	if(strId.CompareNoCase("Description")==0){
		xDescription = str;
		return true;
	}
	if(strId.CompareNoCase("Comment")==0){
		xComment = str;
		return true;
	}

	if(strId.CompareNoCase("AddressSpace")==0){
		xAddresses = str;
		return true;
	}

	if(strId.CompareNoCase("ShowArpDiscoveredHosts")==0){
		xShowArpDiscoveredHosts = BoolFromString(str);
		return true;
	}

	if(strId.CompareNoCase("ScanAll")==0){
		xScanAll = BoolFromString(str);
		return true;
	}

	if(strId.CompareNoCase("ScanOrder")==0){
		scanOrd = (ScanOrder)IntFromString(str);
		switch(scanOrd){
			case __soNumeric :
			case __soRandomized :
				xScanOrder = scanOrd;
				break;

			default:
				xScanOrder = __soAsEntered;
				break;
		}
		return true;
	}

	if(strId.CompareNoCase("MaxSimScan")==0){
		xMaxSimScan = IntFromString(str);
		if(xMaxSimScan<1) xMaxSimScan = 1;
		return true;
	}
	if(strId.CompareNoCase("MaxSimScanDns")==0){
		xMaxSimScanDns = IntFromString(str);
		if(xMaxSimScanDns<1) xMaxSimScanDns = 1;
		return true;
	}
	if(strId.CompareNoCase("MaxSimScanIcmp")==0){
		xMaxSimScanIcmp = IntFromString(str);
		if(xMaxSimScanIcmp<1) xMaxSimScanIcmp = 1;
		return true;
	}
	if(strId.CompareNoCase("MaxWaitTime")==0){
		xMaxWaitTime = IntFromString(str);
		if(xMaxWaitTime<1) xMaxWaitTime = 1;
		return true;
	}
	if(strId.CompareNoCase("MinDelay")==0){
		xMinDelay = (DWORD)(1000*IntFromString(str));
		if(xMinDelay>3600000) xMinDelay = 3600000;
		return true;
	}

	if(strId.CompareNoCase("MimicOS")==0){
		xMimicOS = (MimicOS)IntFromString(str);
		if((int)xMimicOS<0 || (int)xMimicOS>=MAX_COUNT_MIMIC) xMimicOS = __mosRandom;
		return true;
	}

	if(strId.CompareNoCase("ArpCacheOp")==0){
		xArpCacheOp = (ArpCacheOp)IntFromString(str);
		if(xArpCacheOp!=__acoIgnore && xArpCacheOp!=__acoUse  && xArpCacheOp!=__acoUpdate)
			xArpCacheOp = __acoIgnore;
		return true;
	}

	if(strId.CompareNoCase("WorkCfgElem")==0){
		wce.Initialize();
		if(!wce.FromString(str))
			return false;
		if(!AddJob(&wce))
			return false;
		return true;
	}

	return true;
}

//---------------------------------------------------------------------------

bool WorkCfg::InternalSave(void)
{
	WorkCfgElement *wce;

	if(!WriteEmptyCommentLine()) return false;
	if(!WriteCommentLine(_T("CHScanner - Work Configuration File"))) return false;
	if(!AddTimeStampAsComment()) return false;
	if(!WriteEmptyCommentLine()) return false;

	if(!WriteEmptyLine()) return false;

	if(!WriteLineWithId(_T("Description"),  xDescription)) return false;
	if(!WriteLineWithId(_T("Comment"),      xComment)) return false;

	if(!WriteEmptyLine()) return false;

	if(!WriteLineWithId(_T("AddressSpace"), xAddresses)) return false;

	if(!WriteEmptyLine()) return false;


	if(!WriteLineWithId(_T("ShowArpDiscoveredHosts"), BoolToString(xShowArpDiscoveredHosts))) return false;
	if(!WriteLineWithId(_T("ScanAll"),                BoolToString(xScanAll))) return false;
	if(!WriteLineWithId(_T("ScanOrder"),              IntToString((int)xScanOrder))) return false;

	if(!WriteEmptyLine()) return false;

	if(!WriteLineWithId(_T("MaxSimScan"),     IntToString(xMaxSimScan))) return false;
	if(!WriteLineWithId(_T("MaxSimScanDns"),  IntToString(xMaxSimScanDns))) return false;
	if(!WriteLineWithId(_T("MaxSimScanIcmp"), IntToString(xMaxSimScanIcmp))) return false;
	if(!WriteLineWithId(_T("MaxWaitTime"),    IntToString(xMaxWaitTime))) return false;
	if(!WriteLineWithId(_T("MinDelay"),       IntToString((int)xMinDelay/1000))) return false;

	if(!WriteEmptyLine()) return false;

	if(!WriteLineWithId(_T("MimicOS"), IntToString((int)xMimicOS))) return false;

	if(!WriteEmptyLine()) return false;

	if(!WriteLineWithId(_T("ArpCacheOp"), IntToString((int)xArpCacheOp))) return false;

	if(!WriteEmptyLine()) return false;

	for(itor=theVector.begin(); itor!=theVector.end(); itor++){
		wce = *itor;
		if(wce!=NULL){
			if(!WriteLineWithId(_T("WorkCfgElem"), wce->ToString()))
				return false;
		}
	}

	if(!WriteEmptyLine()) return false;

	return true;
}

//---------------------------------------------------------------------------

int WorkCfg::GetJobCount(void)
{
	return (int)theVector.size();
}

WorkCfgElement* WorkCfg::GetJobElement(int idxIn)
{
	if(idxIn<0)          return NULL;
	if(idxIn>=GetJobCount()) return NULL;

	return theVector[idxIn];
}

//---------------------------------------------------------------------------

bool WorkCfgElementGreater(WorkCfgElement* a1, WorkCfgElement* a2)
{
	if(a2==NULL) return true;
	if(a1==NULL) return false;

	if((int)a1->phaseType < (int)a2->phaseType) return true;
	if((int)a1->phaseType > (int)a2->phaseType) return false;
	
	return a1->pos < a2->pos ? true : false;
}

void WorkCfg::SortTheListOfJobs(void)
{
	std::sort(theVector.begin(), theVector.end(), WorkCfgElementGreater);
}

//---------------------------------------------------------------------------

void WorkCfg::Check(void)
{
	if(xMaxSimScan<1)       xMaxSimScan     = 1;
	if(xMaxSimScan>1000)    xMaxSimScan     = 1000;

	if(xMaxSimScanDns<1)    xMaxSimScanDns  = 1;
	if(xMaxSimScanDns>100)  xMaxSimScanDns  = 100;

	if(xMaxSimScanIcmp<1)   xMaxSimScanIcmp = 1;
	if(xMaxSimScanIcmp>100) xMaxSimScanIcmp = 100;

	if(xMaxWaitTime<1)      xMaxWaitTime    = 1;
	if(xMaxWaitTime>10000)  xMaxWaitTime    = 10000;

	if(xMinDelay>3600000)   xMinDelay       = 3600000;
}
//---------------------------------------------------------------------------
